<template>
  <nut-popup 
    :visible="visible" 
    position="bottom" 
    :style="{ height: '85%' }"
    @close="handleClose"
  >
    <view class="generic-selector">
      <!-- 弹窗头部 -->
      <view class="popup-header">
        <text class="popup-title">{{ title }}</text>
        <view class="close-btn" @click="handleClose">
          <text>✕</text>
        </view>
      </view>
      
      <!-- 弹窗内容 -->
      <view class="popup-contents">
        <!-- 筛选框 -->
        <view class="filter-section">
          <view class="filter-input-wrapper">
            <view class="search-icon">
              <text class="icon-text">🔍</text>
            </view>
            <input 
              class="filter-input"
              :placeholder="searchPlaceholder"
              :value="filterText"
              @input="handleFilterInput"
              @focus="handleFilterFocus"
              @blur="handleFilterBlur"
            />
            <view v-if="filterText" class="clear-btn" @click="clearFilter">
              <text class="clear-text">✕</text>
            </view>
          </view>
        </view>

        <!-- 列表内容 -->
        <view class="selection-content">
          <view v-if="loading" class="loading-container">
            <text class="loading-text">正在加载数据...</text>
          </view>
          <view v-else-if="filteredList.length === 0" class="empty-container">
            <text class="empty-text">{{ filterText ? '未找到匹配的数据' : '暂无数据' }}</text>
          </view>
          <view v-else class="item-list">
            <view 
              v-for="item in filteredList" 
              :key="getItemKey(item)"
              class="item"
              :class="{ 'selected': isItemSelected(item) }"
              @click="selectItem(item)"
            >
              <view class="item-info">
                <text class="item-title">{{ getItemTitle(item) }}</text>
                <text v-if="getItemSubtitle(item)" class="item-subtitle">{{ getItemSubtitle(item) }}</text>
              </view>
              <view v-if="isItemSelected(item)" class="selected-icon">
                <text class="check-icon">✓</text>
              </view>
            </view>
          </view>
        </view>
      </view>
    </view>
  </nut-popup>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { request } from '@/utils/request'

interface Props {
  /** 弹窗显示状态 */
  visible: boolean
  /** 弹窗标题 */
  title?: string
  /** 搜索框占位符 */
  searchPlaceholder?: string
  /** 接口URL */
  apiUrl: string
  /** 查询参数 */
  params?: Record<string, any>
  /** 数据字段映射 */
  fieldMapping?: {
    key?: string
    title?: string
    subtitle?: string
  }
  /** 搜索字段 */
  searchFields?: string[]
  /** 是否支持多选 */
  multiple?: boolean
  /** 已选中的项目 */
  selectedItems?: any[]
}

interface Emits {
  /** 更新visible状态事件，用于支持v-model */
  (e: 'update:visible', value: boolean): void
  /** 关闭弹窗事件 */
  (e: 'close'): void
  /** 选择确认事件 */
  (e: 'confirm', data: any | any[]): void
}

const props = withDefaults(defineProps<Props>(), {
  title: '请选择',
  searchPlaceholder: '搜索...',
  params: () => ({}),
  fieldMapping: () => ({
    key: 'id',
    title: 'title',
    subtitle: 'subtitle'
  }),
  searchFields: () => ['title', 'name'],
  multiple: false,
  selectedItems: () => []
})

const emit = defineEmits<Emits>()

// 数据列表
const dataList = ref<any[]>([])
const loading = ref(false)

// 筛选相关状态
const filterText = ref('')
const isFilterFocused = ref(false)

// 已选择的项目
const selectedItems = ref<any[]>([])

// 计算属性：筛选后的列表
const filteredList = computed(() => {
  if (!filterText.value) {
    return dataList.value
  }
  
  const searchText = filterText.value.toLowerCase()
  return dataList.value.filter(item => {
    return props.searchFields.some(field => {
      const value = getNestedValue(item, field)
      return value && value.toString().toLowerCase().includes(searchText)
    })
  })
})

// 获取嵌套对象的值
const getNestedValue = (obj: any, path: string) => {
  return path.split('.').reduce((current, key) => current?.[key], obj)
}

// 获取项目的唯一标识
const getItemKey = (item: any) => {
  const keyField = props.fieldMapping.key || 'id'
  return getNestedValue(item, keyField)
}

// 获取项目标题
const getItemTitle = (item: any) => {
  const titleField = props.fieldMapping.title || 'title'
  return getNestedValue(item, titleField) || ''
}

// 获取项目副标题
const getItemSubtitle = (item: any) => {
  const subtitleField = props.fieldMapping.subtitle || 'subtitle'
  return getNestedValue(item, subtitleField) || ''
}

// 判断项目是否被选中
const isItemSelected = (item: any) => {
  if (props.multiple) {
    return selectedItems.value.some(selected => 
      getItemKey(selected) === getItemKey(item)
    )
  } else {
    return selectedItems.value.length > 0 && 
           getItemKey(selectedItems.value[0]) === getItemKey(item)
  }
}

// 选择项目
const selectItem = (item: any) => {
  if (props.multiple) {
    const existingIndex = selectedItems.value.findIndex(selected => 
      getItemKey(selected) === getItemKey(item)
    )
    
    if (existingIndex > -1) {
      // 如果已选中，则取消选择
      selectedItems.value.splice(existingIndex, 1)
    } else {
      // 如果未选中，则添加到选择列表
      selectedItems.value.push(item)
    }
  } else {
    // 单选模式，直接替换选择
    selectedItems.value = [item]
    // 单选模式自动确认
    setTimeout(() => {
      handleConfirm()
    }, 300)
  }
}

// 确认选择
const handleConfirm = () => {
  const result = props.multiple ? selectedItems.value : selectedItems.value[0]
  emit('confirm', result)
  handleClose()
}

// 关闭弹窗
const handleClose = () => {
  emit('update:visible', false)
  emit('close')
}

// 加载数据
const loadData = async () => {
  try {
    loading.value = true
    const response = await request({
      url: props.apiUrl,
      method: 'GET',
      params: props.params
    })
    
    // 处理不同的响应格式
    let data = []
    if (Array.isArray(response.data)) {
      data = response.data
    } else if (response.data && Array.isArray(response.data.records)) {
      data = response.data.records
    } else if (response.data && Array.isArray(response.data.list)) {
      data = response.data.list
    } else if (response.data && Array.isArray(response.data.data)) {
      data = response.data.data
    } else {
      console.warn('数据格式异常:', response.data)
      data = []
    }
    
    dataList.value = data
  } catch (error) {
    console.error('加载数据失败:', error)
    dataList.value = []
  } finally {
    loading.value = false
  }
}

// 处理筛选输入
const handleFilterInput = (e: any) => {
  filterText.value = e.detail.value
}

// 处理筛选框获得焦点
const handleFilterFocus = () => {
  isFilterFocused.value = true
}

// 处理筛选框失去焦点
const handleFilterBlur = () => {
  isFilterFocused.value = false
}

// 清空筛选
const clearFilter = () => {
  filterText.value = ''
}

// 重置选择状态
const resetSelection = () => {
  selectedItems.value = []
  filterText.value = ''
  isFilterFocused.value = false
}

// 监听弹窗显示状态
watch(() => props.visible, (newVal) => {
  if (newVal) {
    // 弹窗打开时，加载数据
    loadData()
    // 初始化已选择的项目
    selectedItems.value = [...props.selectedItems]
  } else {
    // 弹窗关闭时，重置状态
    resetSelection()
  }
})

// 监听已选择项目变化
watch(() => props.selectedItems, (newVal) => {
  selectedItems.value = [...newVal]
}, { deep: true })

// 暴露方法给父组件
defineExpose({
  resetSelection,
  loadData
})
</script>

<style scoped lang="scss">
.generic-selector {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: white;
  
  .popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 32rpx;
    border-bottom: 1rpx solid #e9ecef;
    background: white;
    
    .popup-title {
      font-size: 32rpx;
      font-weight: 600;
      color: #111827;
    }
    
    .close-btn {
      width: 48rpx;
      height: 48rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      border-radius: 50%;
      transition: background-color 0.2s ease;
      
      &:hover {
        background-color: #f3f4f6;
      }
      
      text {
        font-size: 32rpx;
        color: #6b7280;
      }
    }
  }
  
  .popup-contents {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    
    .filter-section {
      padding: 24rpx 32rpx;
      background: white;
      border-bottom: 1rpx solid #e9ecef;
      
      .filter-input-wrapper {
        position: relative;
        display: flex;
        align-items: center;
        background: #f8f9fa;
        border-radius: 12rpx;
        border: 1rpx solid #e9ecef;
        transition: border-color 0.2s ease;
        
        &:focus-within {
          border-color: #3b82f6;
        }
        
        .search-icon {
          padding: 0 24rpx;
          
          .icon-text {
            font-size: 28rpx;
            color: #9ca3af;
          }
        }
        
        .filter-input {
          flex: 1;
          padding: 24rpx 0;
          border: none;
          background: transparent;
          font-size: 28rpx;
          color: #374151;
          outline: none;
          
          &::placeholder {
            color: #9ca3af;
          }
        }
        
        .clear-btn {
          padding: 0 24rpx;
          cursor: pointer;
          
          .clear-text {
            font-size: 24rpx;
            color: #9ca3af;
          }
        }
      }
    }
    
    .selection-content {
      flex: 1;
      overflow-y: auto;
      
      .loading-container, .empty-container {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 200rpx;
        
        .loading-text, .empty-text {
          font-size: 28rpx;
          color: #9ca3af;
        }
      }
      
      .item-list {
        padding: 16rpx 0;
        
        .item {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 24rpx 32rpx;
          border-bottom: 1rpx solid #f3f4f6;
          cursor: pointer;
          transition: background-color 0.2s ease;
          
          &:hover {
            background-color: #f9fafb;
          }
          
          &.selected {
            background-color: #eff6ff;
            border-color: #3b82f6;
          }
          
          &:last-child {
            border-bottom: none;
          }
          
          .item-info {
            flex: 1;
            
            .item-title {
              font-size: 28rpx;
              color: #374151;
              line-height: 1.5;
              display: block;
              margin-bottom: 8rpx;
            }
            
            .item-subtitle {
              font-size: 24rpx;
              color: #6b7280;
              line-height: 1.4;
              display: block;
            }
          }
          
          .selected-icon {
            margin-left: 16rpx;
            
            .check-icon {
              font-size: 24rpx;
              color: #3b82f6;
              font-weight: bold;
            }
          }
        }
      }
    }
  }
}
</style>
